// pages/pageUpdate/pageUpdate.ts

import { IAppOption } from "../../../typings/index"
import { BluetoothEventCallback, BluetoothManager } from "../../lib/bluetoothManager"
import { OTAConfig, ReConnectMsg, UpgradeType } from "../../lib/rcsp-protocol/jl-ota/jl_ota_2.0.0"
import { Ble051 } from "../../lib/ble-051"

const app = getApp<IAppOption>()
var sBluetoothManager: BluetoothManager
var bluetoothEventCallback: BluetoothEventCallback
var sBle051:Ble051
Page({
  data: {
    isBleConnect:false,
    isShowProgress:false,     //展示OTA升级界面
    mValue:0,                 //进度 0-100
    mNumber:0,                //完成次数
    mTimes:0,                 //测试总次数
    mOtaFile:"", //OTA文件名
    mFailReason:"ota Fail",   //失败原因 
    mOtaResult:0,             //0:成功 1:失败
    mStatus:0,                 //0:检验中 1:升级中 2:回连设备 3:升级成功 4:升级失败

    isShowLoading:false,
    mLoadingText:"加载升级文件",
    device:<any>null,
    speed:0,
    time:0,
    timer:0,
  },
  upgradeData: new Uint8Array(0),
  appArray: new Array(),
  dfuSettingArray:new Array(),

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad() {
    
  },
  onUnload() {
    sBluetoothManager.removeBluetoothEventCallback(bluetoothEventCallback)
  },
  onShow(){
    var device = wx.getStorageSync("device")
    if(!!device){
      device = JSON.parse(device)
      this.setData({
        device:device
      })
      if(device.type == 'gm'){
        sBle051 = new Ble051();
      } else if(device.type == 'jl'){
        sBluetoothManager = app.globalData.bluetoothManager
        bluetoothEventCallback = new BluetoothEventCallback();
          /** 设备断开 */
        bluetoothEventCallback.onDevStatusDisconnect = (dev: WechatMiniprogram.BlueToothDevice)=> { 
          this.setData({
            isBleConnect:false
          })
        };
        /** 设备连接失败 */
        bluetoothEventCallback.onDevStatusFailed = (dev: WechatMiniprogram.BlueToothDevice)=> {
          this.setData({
            isBleConnect:false
          })
         };
        /** 设备连接成功*/
        bluetoothEventCallback.onDevStatusSuccess = (dev: WechatMiniprogram.BlueToothDevice)=> {
          this.setData({
            isBleConnect:true
          })
         };
        sBluetoothManager.addBluetoothEventCallback(bluetoothEventCallback)
      }
    } else {
      this.setData({
        device:null
      })
    }
  },
  onHide(){
    if(!!sBluetoothManager){
      sBluetoothManager.removeBluetoothEventCallback(bluetoothEventCallback)
    }
  },
  searchFun(){
    //Android平台检测是否有开启位置权限，
    let info = wx.getSystemSetting()
    let auth = wx.getAppAuthorizeSetting()
    let device = wx.getDeviceInfo()
    // console.error(info)
    //检测是否有位置权限
    if (device.platform == "android" && !auth.locationAuthorized) {
      wx.showToast({
        title: '请授予微信位置权限(GPS)',
        icon: 'none'
      })
      return
    }
    //检测是否打开gps位置开关
    if (device.platform == "android" && !info.locationEnabled) {
      wx.showToast({
        title: '请打开位置信息(GPS)',
        icon: 'none'
      })
      return
    }
    // 判断是选择固件
    if (this.data.mOtaFile == "") {
      wx.showToast({
        title: '请先选择升级文件',
        icon: 'none'
      })
      return;
    }
    wx.navigateTo({
      url:'../search/index'
    })
  },
  settingFun(){
    wx.navigateTo({
      url:'../pageSetting/pageSetting'
    })
  },
  showLoadingView: function() {
    this.setData({
      isShowLoading:true
    })
  },
  dismissLoadingView: function() {
    this.setData({
      isShowLoading:false
    })
  },
  selectFileFunc: function(e:any) {
    var _this = this;
    // 文件管理器
    const fs = wx.getFileSystemManager()
    wx.chooseMessageFile({
      count: 1,
      type: 'file',
      success: res => {
        var tempFile = res.tempFiles[0];
        // 根据文件类型读取文件
        if (tempFile.name.endsWith(".zip")) {
          // 解压文件
          fs.unzip({
            zipFilePath: tempFile.path,
            targetPath: wx.env.USER_DATA_PATH + '/' + tempFile.time,
            success(res) {
              // 读取解压的文件目录
              fs.readdir({
                dirPath: wx.env.USER_DATA_PATH + '/' + tempFile.time,
                success: res => {
                  fs.readFile({
                    filePath: wx.env.USER_DATA_PATH + '/' + tempFile.time + '/APP1.bin',
                    encoding: 'hex',
                    position: 0,
                    success(res) {
                      _this.appArray =  _this.hexString2Bytes(res.data + "")
                    },
                    fail(res) {
                      wx.showToast({
                        title:'缺失app1.bin'
                      })
                    }
                  })
                  fs.readFile({
                    filePath: wx.env.USER_DATA_PATH + '/' + tempFile.time + '/dfu_setting.dat',
                    encoding: 'hex',
                    position: 0,
                    success(res) {
                      _this.dfuSettingArray =  _this.hexString2Bytes(res.data + "")
                    },
                    fail(res) {
                      wx.showToast({
                        title:'缺失dfu_setting.dat'
                      })
                    }
                  })
                  setTimeout(() => {
                    wx.showToast({
                      title:'加载成功',
                      icon: 'none'
                    })
                  }, 200);
                  // 读取完成，显示文件名称
                  _this.setData({
                    mOtaFile:tempFile.name
                  })
                }
              })
            },
            fail(res) {
              wx.showToast({
                title:'文件读取失败',
                icon:'error'
              })
            }
          })
        } else if(tempFile.name.endsWith(".ufw")){
          this.setData({
            mOtaFile:tempFile.name
          })
          let fd = fs.openSync({
            filePath:tempFile.path
          })
          let uint8 = new Uint8Array(tempFile.size);
          fs.read({
            fd:fd,
            arrayBuffer:uint8.buffer,
            length:tempFile.size,
            success: _res => {
              this.upgradeData = uint8
              console.log("------------读取文件成功------------")
              setTimeout(() => {
                wx.showToast({
                  title: '加载成功',
                  icon: 'none'
                })
              }, 200);
              // 读取完成，显示文件名称
              _this.setData({
                mOtaFile:tempFile.name
              })
              fs.closeSync({ fd: fd })
            },
            fail: _res => {
              wx.showToast({
                title: '加载失败',
                icon: 'none'
              })
              fs.closeSync({ fd: fd })
            }
          })
        } else {
          wx.showToast({
            title:'不支持的文件格式',
          })
        }
      },
      fail: e => {
        console.error(e)
      }
    })
  },
  onUpdate: function(){
    if (this.data.mOtaFile == "") {
      wx.showToast({
        title: '请先选择升级文件',
        icon: 'none'
      })
      return;
    }
    var device = this.data.device
    if (!!!device){
      wx.showToast({
        title: '请先连接设备',
        icon: 'none'
      })
      return;
    }
    this.setData({
      time:0,
      mValue:0,
      mStatus:0,
      mOtaResult:0,
    })
    // 判断设备类型
    if(device.type == "gm"){
      this.onUpdate_gm();
      return
    }
    if(device.type =="jl"){
      this.onUpdate_jl();
      return
    }
  },
  onUpdate_gm:function(){
    if(this.dfuSettingArray.length == 0){
      wx.showToast({
        title:'dfu文件缺失'
      })
      return
    }
    if(this.appArray.length == 0){
      wx.showToast({
        title:'app文件缺失'
      })
      return
    }
    var device = this.data.device
    console.log("开始升级(GM)")
    this.setData({
      isShowProgress : true,
    })
    var that = this;
    sBle051.connectDevice(device.deviceId,function(res:any){
      sBle051.onConnectStatus = null
      // 判断连接是否成功
      if(res.data.connectStatus){
        // 延时3秒
        setTimeout(() => {
          sBle051.updateBleConnectDuration()
          setTimeout(() => {
            sBle051.updateBleMtu()
          }, 1000);
          setTimeout(() => {
            sBle051.selectVersion()
          }, 2000);
          setTimeout(() => {
            sBle051.jumpToImageUpdate()
          }, 3000);
          setTimeout(() => {
            that.setData({
              mStatus:2
            })
            console.log("断开连接")
            sBle051.disConnectDevice(function(){
              console.log("开始重连")
              setTimeout(() => {
                sBle051.connectDevice(device.deviceId,function(res:any){
                  sBle051.onConnectStatus = null
                  // 判断连接是否成功
                  if(res.data.connectStatus){
                    setTimeout(() => {
                      // 先获取一下MTU值
                      wx.getBLEMTU({
                        deviceId: device.deviceId,
                        writeType: 'writeNoResponse',
                        success (res) {
                          console.log("获取MTU值：",res.mtu)
                          // 最大值为244
                          if (res.mtu -3 > 244){
                            sBle051.mtu = 244
                          } else {
                            sBle051.mtu = res.mtu -3
                          }
                        }
                      })
                      that.setData({
                        mStatus:1
                      })
                      // 组装数据，dfu文件+app文件
                      let dataArray = new Array()
                      for(let i=0;i<that.dfuSettingArray.length;i++){
                        dataArray.push(that.dfuSettingArray[i])
                      }
                      for(let i=0;i<that.appArray.length;i++){
                        dataArray.push(that.appArray[i])
                      }
                      console.log("正在发送升级数据...")
                      // 延时执行
                      setTimeout(() => {
                        // 定时器，20毫秒发送一次
                        let startIndex = 0;
                        let endIndex = startIndex + sBle051.mtu;
                        let timer = setInterval(function name() {
                          // 说明是最后一包数据
                          if (endIndex >= dataArray.length){
                            sBle051.sendUpgradeData(dataArray.slice(startIndex,dataArray.length))
                            //mValue
                            that.setData({
                              mValue:100,
                            })
                            clearInterval(timer)
                            setTimeout(() => {
                              sBle051.flashCheck()
                            }, 1000);
                            setTimeout(() => {
                              sBle051.activeAndReset()
                              that.setData({
                                mStatus:3
                              })
                            }, 2000)
                            setTimeout(() => {
                              // 关闭连接
                              sBle051.disConnectDevice(function(){})
                              console.log("升级结束，关闭连接")
                            }, 2500);
                          } else {
                            // 中间包
                            // 计算升级进度
                            that.setData({
                              mValue:(endIndex / dataArray.length) * 100,
                            })
                            sBle051.sendUpgradeData(dataArray.slice(startIndex,endIndex))
                          }
                          startIndex += sBle051.mtu;
                          endIndex = startIndex + sBle051.mtu;
                        },20)
                      }, 1000);
                    }, 3000);
                  } else {
                    that.setData({
                      mValue : 0,
                      mOtaResult:1,
                      mStatus:4,
                      mFailReason:'重连失败'
                    })
                    return
                  }
                })
              }, 10000);
            })
          }, 4000);
        }, 3000);
      } else {
        that.setData({
          mValue : 0,
          mStatus:4,
          mOtaResult:1,
          mFailReason:'连接失败'
        })
      }
    })
  },
  onUpdate_jl:function(){
    console.log("开始升级(JL)")
    this.setData({
      isShowProgress : true,
    })
    var that = this;
    if(sBluetoothManager.connectDevice(this.data.device,false)){
      setTimeout(() => {
      /*--- 开始执行OTA升级 ---*/
      const otaConfig: OTAConfig = new OTAConfig()
      otaConfig.isSupportNewRebootWay = true
      otaConfig.updateFileData = this.upgradeData
      console.log("upgradeData size: " + this.upgradeData.length);
      sBluetoothManager.startOTA(otaConfig,{
        onStartOTA: () => {
          var t = setInterval(function(){
            that.setData({
              time:that.data.time + 1
            })
          },1000)
          this.setData({
            timer:t
          })
        },
        onNeedReconnect: (reConnectMsg: ReConnectMsg) => {
          this.setData({
            mValue : 0,
            mStatus: 2
          })
        },
        onProgress: (type: UpgradeType, progress: number) => {
          if (type == UpgradeType.UPGRADE_TYPE_CHECK_FILE) {
            this.setData({
              mValue : progress,
              mStatus: 0
            })
          }
          if (type == UpgradeType.UPGRADE_TYPE_FIRMWARE) {
            this.setData({
              mValue : progress,
              mStatus: 1
            })
          }
        },
        onStopOTA: () => {
          this.setData({
            mValue : 0,
            mOtaResult:0,
            mStatus: 3
          })
          this.closeTimer()
        },
        onCancelOTA: () => {
          this.setData({
            mValue : 0,
            mOtaResult:1,
            mStatus: 4,
            mFailReason:"升级被取消."
          })
          this.closeTimer()
        },
        onError: (error: number, message: string) => {
          this.setData({
            mValue : 0,
            mOtaResult:1,
            mStatus: 4,
            mFailReason:message
          })
          this.closeTimer()
        },
      })
      }, 3000);
    } else {
      this.setData({
        mValue : 0,
        mOtaResult:1,
        mStatus:4,
        mFailReason:'连接失败'
      })
    }
  },
  hexString2Bytes: function(hexString:string) : Array<Int32Array> {
    var pos = 0;
    var len = hexString.length;
    if (len % 2 != 0) {
      return [];
    }
    len /= 2;
    var hexA = new Array();
    for (var i = 0; i < len; i++) {
      var s = hexString.substr(pos, 2);
      var v = parseInt(s, 16);
      hexA.push(v);
      pos += 2;
    }
    return hexA;
  },

  onOtaProgressViewConfirm:function(){
    this.setData({
      isShowProgress : false
    })
  },

  closeTimer:function(){
    clearInterval(this.data.timer)
    this.setData({
      time:0,
      timer:0,
    })
  }
})